# -*- coding: utf-8 -*-
'''
Created on 2013-4-11

@author: cl.lam
'''
from datetime import datetime as dt
import traceback
from flask import current_app as app
from flask import g, render_template, flash, session, redirect, url_for, request
from flask.blueprints import Blueprint
from sqlalchemy.sql.expression import and_, not_, desc
from sqlalchemy.orm.exc import NoResultFound


from sys2do.views import BasicView
from sys2do.util.decorator import templated, loginRequired, activetab, \
    mypaginate
from sys2do.model import db, qry, Product

from sys2do.util.common import _g, _gld, multiupload, _gp, _gl, upload, \
    makeThumb
from sys2do.util.logic_helper import getCurrentShopID, getCurrentUserID, \
    checkLogin, getOption, makeUpdateLog
from sys2do.constant import MSG_SAVE_SUCC, TAB_BASIC, MSG_SERVER_ERROR, \
    MESSAGE_ERROR, MESSAGE_INFO, MSG_UPDATE_SUCC, MSG_NOT_ENOUGH_PARAMS, \
    MSG_RECORD_NOT_EXIST, ACTIVE, LOG_TYPE_CREATE, LOG_TYPE_UPDATE
from sys2do.model import ProductType, SysLog, ProductSeries, ProductShap, SysFile
from sys2do.util.barcode_helper import genBarcodeFile




__all__ = ['bpPdt']

bpPdt = Blueprint( 'bpPdt', __name__ )

@bpPdt.before_request
def _b():
    return checkLogin()

class ProductView( BasicView ):

    template_folder = "mas.pdt"

    @templated( "index.html" )
    @activetab( TAB_BASIC )
    @mypaginate( 'result' )
    def index( self ):
        if request.method == 'POST':
            form = SrhForm( request.form )
            session[url_for( '.view' )] = form
        else:
            form = session.get( url_for( '.view' ), SrhForm( request.form ) )
        form.url = url_for( '.view' )
        form.typeID.choices = getOption( ProductType, [ProductType.active == ACTIVE, ], ProductType.name )
        form.seriesID.choices = getOption( ProductSeries, [ProductSeries.active == ACTIVE, ], ProductSeries.name )
        form.shapID.choices = getOption( ProductShap, [ProductShap.active == ACTIVE, ], ProductShap.name )

        cds = [ Product.active == 0, ]
        if form.no.data : cds.append( Product.no.like( '%%%s%%' % form.no.data ) )
        if form.barcode.data : cds.append( Product.barcode.like( '%%%s%%' % form.barcode.data ) )
        if form.name.data : cds.append( Product.name.like( '%%%s%%' % form.name.data ) )
        if form.styleNo.data : cds.append( Product.styleNo.like( '%%%s%%' % form.styleNo.data ) )
        if form.certificate.data : cds.append( Product.certificate.like( '%%%s%%' % form.certificate.data ) )
        if form.createTimeFrom.data : cds.append( Product.createTime > form.createTimeFrom.data )
        if form.createTimeTo.data : cds.append( Product.createTime < form.createTimeTo.data )
        if form.typeID.data and form.typeID.data != 'None' : cds.append( Product.typeID == form.typeID.data )
        if form.seriesID.data and form.typeID.data != 'None' : cds.append( Product.seriesID == form.seriesID.data )
        if form.shapID.data and form.typeID.data != 'None' : cds.append( Product.shapID == form.shapID.data )
        rs = Product.iall( cds, order_by = Product.no )
        return {'result' : rs, 'form' : form}


    @templated( "view.html" )
    def view( self ):
        pid = _g( 'id' )
        if not pid :
            flash( MSG_NOT_ENOUGH_PARAMS, MESSAGE_ERROR )
            return redirect( url_for( '.view' ) )
        obj = Product.get( pid )
        if obj is None:
            flash( MSG_RECORD_NOT_EXIST, MESSAGE_ERROR )
            return redirect( url_for( '.view' ) )
        else:
            if not obj.barcodeImgID:
                fobj = genBarcodeFile( obj.no )
                db.add( fobj )
                obj.barcodeImg = fobj
                db.commit()
        return {'obj' : obj}


    def viewByNo( self ):
        pno = _g( 'no' )
        if not pno :
            flash( MSG_NOT_ENOUGH_PARAMS, MESSAGE_ERROR )
            return redirect( url_for( '.view' ) )
        try:
            obj = qry( Product ).filter( and_( Product.active == 0 , Product.no == pno ) ).one()
            return {'obj' : obj}
        except NoResultFound:
            flash( MSG_RECORD_NOT_EXIST, MESSAGE_ERROR )
            return redirect( url_for( '.view' ) )


    @templated( "add.html" )
    @activetab( TAB_BASIC )
    @loginRequired
    def add( self ):
        if request.method != 'POST':
            pts = ProductType.iall( [ProductType.active == 0] )
            return {'pts' : pts}

        try:
            params = _gld( 'name', 'typeID', 'shapID', 'seriesID', 'pPrice',
                           'styleNo', 'weight', 'length', 'clarity', 'color',
                           'goldFineness', 'certificate', 'length', 'width', 'height',
                           'sPrice', 'remark' )

            isDeploy = _gl( 'isDeploy' )
            if not isDeploy : params['isDeploy'] = 0
            else : params['isDeploy'] = isDeploy[0]

            realImg = upload( 'realImgID' )
            if realImg :
                params['realImg'] = realImg
                thumb = makeThumb( realImg )
                if thumb : params['thumb'] = thumb

            params['image'] = multiupload( [name for name in request.files if name.startswith( "img_" )] )
            params['attachment'] = multiupload( [name for name in request.files if name.startswith( "atm_" )] )
            obj = Product.create( params )
#             obj.assignNo()
            db.add( obj )
            db.flush()
#             b = Barcode.getOrCreate(no, obj.no)
            db.add( genBarcodeFile( obj.no ) )
            db.add( SysLog( refClz = obj.__class__.__name__, type = LOG_TYPE_CREATE, refID = obj.id, ) )
            flash( MSG_SAVE_SUCC, MESSAGE_INFO )
            db.commit()
        except:
            db.rollback()
            traceback.print_exc()
            flash( MSG_SERVER_ERROR, MESSAGE_ERROR )
        return redirect( url_for( '.view' ) )


    @templated( "update.html" )
    @activetab( TAB_BASIC )
    @loginRequired
    def update( self ):
        obj = Product.get( _g( 'id' ) )
        if request.method != 'POST':
            pts = ProductType.iall( [ProductType.active == 0] )
            return {'pts' : pts, 'obj' : obj}

        try:
            oldCopy = obj.serialize()
            extLog = []

            params = _gld( 'name', 'typeID', 'shapID', 'seriesID', 'pPrice',
                           'styleNo', 'weight', 'length', 'clarity', 'color',
                           'goldFineness', 'certificate', 'length', 'width', 'height',
                           'sPrice', 'remark' )

            isDeploy = _gl( 'isDeploy' )
            if not isDeploy : params['isDeploy'] = 0
            else : params['isDeploy'] = isDeploy[0]

            realImg = upload( 'realImgID' )
            if realImg :
                params['realImg'] = realImg
                thumb = makeThumb( realImg )
                if thumb : params['thumb'] = thumb

            params.update( {
                           'createById' : getCurrentUserID(),
                           'updateTime' : dt.now(),
                           } )
            obj.update( params )

            #===================================================================
            # process the images
            #===================================================================
            oldiset = set( map( lambda v : unicode( v.id ), obj.image ) )
            newiset = set( filter( bool, _g( 'image', '' ).split( "|" ) ) )
            deltedImg = oldiset.difference( newiset )
            if deltedImg :
                delImgs = qry( SysFile ).filter( SysFile.id.in_( list( deltedImg ) ) )
                extLog.extend( [u'删除图片[%s]。' % da.name for da in delImgs] )
            obj.image = sorted( list( newiset ) ) + multiupload( [name for name in request.files if name.startswith( "img_" )] )

            #===================================================================
            # process the attachment
            #===================================================================
            oldaset = set( map( lambda v : unicode( v.id ), obj.attachment ) )
            newaset = set( filter( bool, _g( 'attachment', '' ).split( "|" ) ) )
            deltedAtm = oldaset.difference( newaset )
            if deltedAtm :
                delAtms = qry( SysFile ).filter( SysFile.id.in_( list( deltedAtm ) ) )
                extLog.extend( [u'删除附件[%s]。' % da.name for da in delAtms] )
            obj.attachment = sorted( list( newaset ) ) + multiupload( [name for name in request.files if name.startswith( "atm_" )] )

            newCopy = obj.serialize()
            makeUpdateLog( obj, oldCopy, newCopy, extLog )
            db.commit()
            flash( MSG_UPDATE_SUCC, MESSAGE_INFO )
        except:
            db.rollback()
            flash( MSG_SERVER_ERROR, MESSAGE_ERROR )
            traceback.print_exc()
        return redirect( url_for( '.view', action = 'view', id = obj.id ) )


    @templated( 'view_log.html' )
    def viewLog( self ):
        pid = _g( 'id' )
        if not pid :
            flash( MSG_NOT_ENOUGH_PARAMS, MESSAGE_ERROR )
            return redirect( url_for( '.view' ) )
        obj = Product.get( pid )
        result = SysLog.iall( conditions = [SysLog.active == ACTIVE ,
                                SysLog.type == Product.__class__.__name__,
                                SysLog.refID == obj.id], order_by = desc( SysLog.sysCreateTime ) )
        return {'obj' : obj, 'records' : result }


    @templated( 'batch_update.html' )
    def batchUpdate( self ):
        pdtids = _gl( 'pdt' )
        if not pdtids :
            flash( MSG_NOT_ENOUGH_PARAMS, MESSAGE_ERROR )
            return redirect( url_for( '.view' ) )

        if type( pdtids ) != list : pdtids = [pdtids, ]
        result = qry( Product ).filter( and_( Product.active == ACTIVE, Product.id.in_( pdtids ) ) ).order_by( Product.name )
        return {'result' : result}


    def saveBatch( self ):
        pdts = _gp( 'pdt_' )
        if not pdts :
            flash( MSG_NOT_ENOUGH_PARAMS, MESSAGE_ERROR )
            return redirect( url_for( '.view' ) )
        try:
            for k, pid in pdts:
                obj = Product.get( pid )
                if obj is None : continue
                if not obj.editable() : continue
                obj.barcode = _g( 'barcode_%s' % pid )
                obj.name = _g( 'name_%s' % pid )
                obj.styleNo = _g( 'styleNo_%s' % pid )
                obj.pPrice = _g( 'pPrice_%s' % pid )
                obj.sPrice = _g( 'sPrice_%s' % pid )
                obj.updateById = getCurrentUserID()
                obj.updateTime = dt.now()
                db.add( SysLog( refClz = obj.__class__.__name__, type = LOG_TYPE_UPDATE, refID = obj.id, ) )
            db.commit()
            flash( MSG_UPDATE_SUCC, MESSAGE_INFO )
        except:
            traceback.print_exc()
            db.rollback()
            flash( MSG_SERVER_ERROR, MESSAGE_ERROR )
        return redirect( url_for( '.view' ) )


    @templated( 'label.html' )
    def printLabel( self ):
        pid = _g( 'id' )
        if not pid :
            flash( MSG_NOT_ENOUGH_PARAMS, MESSAGE_ERROR )
            return redirect( url_for( ".view" ) )

        obj = Product.get( pid )
        if not obj :
            flash( MSG_RECORD_NOT_EXIST, MESSAGE_ERROR )
            return redirect( url_for( ".view" ) )

        return {'obj' : obj}

bpPdt.add_url_rule( '/', view_func = ProductView.as_view( 'view' ), defaults = {'action':'index'} )
bpPdt.add_url_rule( '/<action>', view_func = ProductView.as_view( 'view' ) )



#===============================================================================
# form class
#===============================================================================

from wtforms import Form, TextField, SelectField
from sys2do.util.wt_helper import MyDateField

class SrhForm( Form ):
    no = TextField( u'商品编号', )
    barcode = TextField( u'商品条码', )
    name = TextField( u'商品名称', )
    styleNo = TextField( u'款号', )
    certificate = TextField( u'证书号', )
    typeID = SelectField( u'商品类型', )
    seriesID = SelectField( u'系列', )
    shapID = SelectField( u'形状', )
    createTimeFrom = MyDateField( u'创建时间(开始)' )
    createTimeTo = MyDateField( u'创建时间(结束)' )
